using Fusion.Frameworks.Assets.Editor;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEditor.SceneManagement;
using UnityEngine;

namespace Fusion.Frameworks.Editor
{
    public static class BuilderCallback
    {
        public static Action OnBuildAssetsBefore;
        public static Action OnBuildAssetsAfter;
        public static Action OnBuildPlayerBefore;
        public static Action OnBuildPlayerAfter;
    }


    public class Builder
    {
        private static Dictionary<BuildTarget, string> targetSuffix = new Dictionary<BuildTarget, string> {
            { BuildTarget.StandaloneWindows, ".exe" },
            { BuildTarget.StandaloneWindows64, ".exe" },
            { BuildTarget.Android, ".apk" },
        };

        private static string filePathPrefix = "Assets/GameAssets";
        private static BuildSetting buildSetting = null;

        static Builder(){
            string settingName = $"{filePathPrefix}/BuildSetting.asset";
            buildSetting = AssetDatabase.LoadAssetAtPath<BuildSetting>(settingName);
            if (buildSetting == null)
            {
                CreateGameAssetsFolder();
                buildSetting = ScriptableObject.CreateInstance<BuildSetting>();
                AssetDatabase.CreateAsset(buildSetting, settingName);
                AssetDatabase.Refresh();
            }
        }

        public static BuildSetting BuildSetting { get => buildSetting; }
        public static string FilePathPrefix { get => filePathPrefix; }

        public static void CreateGameAssetsFolder()
        {
            int divideIndex = filePathPrefix.IndexOf("/");
            if (divideIndex != -1)
            {
                if (!AssetDatabase.IsValidFolder(filePathPrefix))
                {
                    AssetDatabase.CreateFolder("Assets", filePathPrefix.Substring(divideIndex + 1));
                }
            }

            AssetDatabase.Refresh();
        }

        [MenuItem("Build/Build", false, 2002)]
        public static void BuildAll()
        {
            BuildAssets();
            BuildPlayer();
        }

        [MenuItem("Build/BuildAssets", false, 1000)]
        public static void BuildAssets()
        {
            BuildDynamic();
            AssetsPacker.CopyAssetsToStreamingAssets();
        }

        [MenuItem("Build/BuildDynamic", false, 2001)]
        public static void BuildDynamic()
        {
            if (BuilderCallback.OnBuildAssetsBefore != null)
            {
                BuilderCallback.OnBuildAssetsBefore();
            }
            AssetsPacker.Build();
            if (BuilderCallback.OnBuildAssetsAfter != null)
            {
                BuilderCallback.OnBuildAssetsAfter();
            }
        }

        [MenuItem("Build/BuildPlayer", false, 1001)]
        public static void BuildPlayer()
        {
            if (BuilderCallback.OnBuildPlayerBefore != null)
            {
                BuilderCallback.OnBuildPlayerBefore();
            }

            string path = null;
            if (buildSetting.initScene != null)
            {
                path = AssetDatabase.GetAssetPath(buildSetting.initScene);
            }
            else
            {
                path = EditorSceneManager.GetActiveScene().path;
            }
            BuildTarget target = GetCurrentBuildTarget();
            string output = $"Output/{target}";
            if (!Directory.Exists(output))
            {
                Directory.CreateDirectory(output);
            }

            string suffix = targetSuffix.ContainsKey(target) ? targetSuffix[target] : "";

            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
            buildPlayerOptions.scenes = new[] { path };
            buildPlayerOptions.locationPathName = $"{output}/{Application.productName}{suffix}";
            buildPlayerOptions.target = target;
            buildPlayerOptions.options = BuildOptions.None;

            if (buildSetting.buildMode == BuildMode.Debug)
            {
                buildPlayerOptions.options |= (BuildOptions.Development | BuildOptions.ConnectWithProfiler | BuildOptions.AllowDebugging);
            }
            else
            {
                buildPlayerOptions.options &= ~(BuildOptions.Development | BuildOptions.ConnectWithProfiler | BuildOptions.AllowDebugging);
            }


            BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
            BuildSummary summary = report.summary;

            if (summary.result == BuildResult.Succeeded)
            {
                Debug.Log("Build succeeded: " + summary.totalSize + " bytes");
                System.Diagnostics.Process.Start("explorer.exe", output.Replace("/", "\\"));
            }

            if (summary.result == BuildResult.Failed)
            {
                Debug.Log("Build failed");
            }
            if (BuilderCallback.OnBuildPlayerAfter != null)
            {
                BuilderCallback.OnBuildPlayerAfter();
            }
        }

        public static BuildTarget GetCurrentBuildTarget()
        {
            BuildTarget buildTarget = (buildSetting == null || buildSetting.buildTargetType == BuildTargetType.UseCurrentTarget) ? EditorUserBuildSettings.activeBuildTarget : (BuildTarget)buildSetting.buildTargetType;
            return buildTarget;
        }

    }
}


